package com.tencent.sr.iris.activity.dependency.user;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.RateLimiter;
import com.tencent.sr.bizmid.user.core.interfaces.client.UserCoreBaseClient;
import com.tencent.sr.bizmid.user.core.interfaces.dto.ChannelUserIdentifyDTO;
import com.tencent.sr.bizmid.user.core.interfaces.dto.UserChannelAccountDTO;
import com.tencent.sr.bizmid.user.core.interfaces.dto.UserCoreDTO;
import com.tencent.sr.bizmid.user.core.interfaces.enums.ChannelType;
import com.tencent.sr.bizmid.user.core.interfaces.enums.UserGroup;
import com.tencent.sr.bizmid.user.core.interfaces.request.BatchQueryChannelAccountRequest;
import com.tencent.sr.bizmid.user.core.interfaces.request.ChannelAccountQueryRequest;
import com.tencent.sr.bizmid.user.core.interfaces.request.UserCoreQueryRequest;
import com.tencent.sr.bizmid.user.core.interfaces.response.ChannelAccountQueryResponse;
import com.tencent.sr.bizmid.user.core.interfaces.response.UserCoreQueryResponse;
import com.tencent.sr.iris.activity.common.config.DependencyConfig;
import com.tencent.sr.iris.activity.common.constant.CommonConstant;
import com.tencent.sr.iris.activity.common.exception.BizCommErrorCode;
import com.tencent.sr.iris.activity.common.util.HttpUtil;
import com.tencent.sr.iris.user.core.service.interfaces.client.activity.IrisUserActivityClient;
import com.tencent.sr.iris.user.core.service.interfaces.client.relation.SupervisorRelationClient;
import com.tencent.sr.iris.user.core.service.interfaces.client.tutor.IrisTutorRelationManageClient;
import com.tencent.sr.iris.user.core.service.interfaces.client.user.IrisUserInfoClient;
import com.tencent.sr.iris.user.core.service.interfaces.client.user.UserWideCoreClient;
import com.tencent.sr.iris.user.core.service.interfaces.dto.tutor.UserTutorRelationDTO;
import com.tencent.sr.iris.user.core.service.interfaces.dto.user.IrisUserDTO;
import com.tencent.sr.iris.user.core.service.interfaces.dto.user.UserWideDTO;
import com.tencent.sr.iris.user.core.service.interfaces.enums.IrisUserSourceFromEnum;
import com.tencent.sr.iris.user.core.service.interfaces.request.activity.SpecialInviteRequest;
import com.tencent.sr.iris.user.core.service.interfaces.request.activity.UserLevelRequest;
import com.tencent.sr.iris.user.core.service.interfaces.request.level.UserBaseRequest;
import com.tencent.sr.iris.user.core.service.interfaces.request.tutor.StudentQueryRequest;
import com.tencent.sr.iris.user.core.service.interfaces.request.tutor.TutorBaseRequest;
import com.tencent.sr.iris.user.core.service.interfaces.request.user.*;
import com.tencent.sr.iris.user.core.service.interfaces.response.activity.*;
import com.tencent.sr.iris.user.core.service.interfaces.response.user.UserInfoQueryResponse;
import com.tencent.sr.iris.user.core.service.interfaces.response.user.UserLevelCountResponse;
import com.tencent.sr.iris.user.core.service.interfaces.response.user.UserUnionIdResponse;
import com.tencent.sr.iris.user.core.service.interfaces.response.user.UserWideListResponse;
import com.tencent.sr.rmall.common.exception.retail.TRetailBizException;
import com.tencent.sr.rmall.common.exception.retail.TRetailErrorException;
import com.tencent.sr.rmall.common.primitive.HttpResult;
import com.tencent.sr.rmall.common.request.PaginationRequest;
import com.tencent.sr.rmall.common.response.PaginationResponse;
import com.tencent.sr.rmall.springbootstarter.route.TsfTagUtils;
import com.tencent.sr.rmall.springbootstarter.utils.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.util.Pair;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

@Slf4j
@Component
public class UserCoreDependency {

    private static final String BIZ_TYPE = "NORMAL_SAAS";

    @Value("${iris.saasId}")
    private Long saasId;

    @Resource
    private IrisUserInfoClient irisUserInfoClient;

    @Resource
    private IrisTutorRelationManageClient irisTutorRelationManageClient;

    @Resource
    private UserCoreBaseClient userCoreBaseClient;

    @Resource
    private UserWideCoreClient userWideCoreClient;

    @Resource
    private IrisUserActivityClient irisUserActivityClient;

    @Resource
    private DependencyConfig dependencyConfig;

    private RateLimiter USER_WIDE_LIST_RATELIMITER = RateLimiter.create(20);

    private RateLimiter USER_INFO_RATELIMITER = RateLimiter.create(20);

    private RateLimiter USER_CORE_INFO_RATELIMITER = RateLimiter.create(20);


    public UserInfoQueryResponse queryUserInfo(String uid, boolean throwOnFail) {
        UserInfoQueryRequest request = new UserInfoQueryRequest();
        request.setUid(uid);
        acquire("queryUserInfo", USER_INFO_RATELIMITER, request, "调用UserDependency.queryUserInfo");
        HttpResult<UserInfoQueryResponse> result = irisUserInfoClient.queryUserInfo(request);
        log.info("调用UserCoreDependency.queryUserInfo，req：{}，response：{}", request, result);
        if (result.isSuccess() && Objects.nonNull(result.getData())) {
            return result.getData();
        }
        if (throwOnFail) {
            throw new TRetailErrorException("查询用户信息失败");
        }
        return new UserInfoQueryResponse();
    }

    /**
     * 限流
     * @param configName
     * @param limiter
     * @param request
     * @param msg
     */
    private void acquire(String configName, RateLimiter limiter, Object request, String msg) {
        DependencyConfig.Config config = dependencyConfig.getConfigs().get(configName);
        if (config != null && config.getPermitsPerSecond() != null) {
            limiter.setRate(config.getPermitsPerSecond());
            limiter.acquire();
            log.info(new StringBuilder(msg).append("，限流{}qps，请求参数：{}").toString(), limiter.getRate(),
                    JSON.toJSONString(request));
        }
    }

    public PaginationResponse<UserTutorRelationDTO> queryTutorStudentList(
            PaginationRequest<StudentQueryRequest> request) {
        HttpResult<PaginationResponse<UserTutorRelationDTO>> result = irisTutorRelationManageClient
                .queryTutorStudentList(request);
        if (result.isSuccess() && Objects.nonNull(result.getData())) {
            return result.getData();
        }
        return new PaginationResponse<>();
    }

    public HttpResult<ChannelAccountQueryResponse> batchQueryChannelAccount(BatchQueryChannelAccountRequest request) {
        return userCoreBaseClient.batchQueryChannelAccount(request);
    }

    /**
     * 根据uid获取导师企微信息
     *
     * @param uid
     * @return
     */
    public ChannelUserIdentifyDTO queryChannelAccount(String uid, Long saasId) {
        ChannelAccountQueryRequest request = new ChannelAccountQueryRequest();
        request.setUid(uid);
        request.setSaasId(saasId);
        request.setBizType(BIZ_TYPE);
        request.setChannelType(ChannelType.UNION_ID.getType());
        request.setUserGroup(UserGroup.GROUP_C.getType());
        HttpResult<ChannelAccountQueryResponse> result = userCoreBaseClient.queryChannelAccountList(request);
        if (result != null && result.isSuccess() && Objects.nonNull(result.getData())) {
            log.info("userCoreDependency.queryChannelAccountList successRequest:{} response = {}",
                    JsonUtils.toJsonString(request), result);
            ChannelAccountQueryResponse data = result.getData();
            List<UserChannelAccountDTO> channelAccountDTOList = data.getChannelAccountDTOList();
            if (!CollectionUtils.isEmpty(channelAccountDTOList)) {
                UserChannelAccountDTO userChannelAccountDTO = channelAccountDTOList.get(0);
                if (Objects.nonNull(userChannelAccountDTO) && Objects.nonNull(
                        userChannelAccountDTO.getChannelUserIdentifyDTO())) {
                    return userChannelAccountDTO.getChannelUserIdentifyDTO();
                }
            }
        }
        return new ChannelUserIdentifyDTO();
    }

    /**
     * 通过uid获取unionId（默认只过滤了删除的账号）
     *
     * @param uid
     * @return
     */
    public String queryUnionIdByUid(String uid) {
        ChannelAccountQueryRequest channelAccountQueryRequest = new ChannelAccountQueryRequest();
        channelAccountQueryRequest.setUid(uid);
        channelAccountQueryRequest.setBizType("NORMAL_SAAS");
        channelAccountQueryRequest.setUserGroup(UserGroup.GROUP_C.getType());
        channelAccountQueryRequest.setChannelType(ChannelType.UNION_ID.getType());
        HttpResult<ChannelAccountQueryResponse> response = userCoreBaseClient
                .queryChannelAccountList(channelAccountQueryRequest);
        if (Objects.nonNull(response) && response.isSuccess()) {
            ChannelAccountQueryResponse data = response.getData();
            if (Objects.nonNull(data) && CollectionUtils.isNotEmpty(data.getChannelAccountDTOList())) {
                return data.getChannelAccountDTOList().get(0).getChannelAccount();
            }
        }
        return null;
    }

    public Pair<String/*unionId*/, String/*openId*/> queryUnionOpenIdByUid(String uid) {
        ChannelAccountQueryRequest channelAccountQueryRequest = new ChannelAccountQueryRequest();
        channelAccountQueryRequest.setUid(uid);
        channelAccountQueryRequest.setBizType("NORMAL_SAAS");
        channelAccountQueryRequest.setUserGroup(UserGroup.GROUP_C.getType());
        channelAccountQueryRequest.setChannelType(ChannelType.WX_MINI_PROGRAM.getType());
        HttpResult<ChannelAccountQueryResponse> response = userCoreBaseClient
                .queryChannelAccountList(channelAccountQueryRequest);
        if (Objects.nonNull(response) && response.isSuccess()) {
            ChannelAccountQueryResponse data = response.getData();
            if (Objects.nonNull(data) && CollectionUtils.isNotEmpty(data.getChannelAccountDTOList())) {
                UserChannelAccountDTO userChannelAccountDTO = data.getChannelAccountDTOList().stream()
                        .filter(item -> Objects.equals(CommonConstant.ZERO, item.getStatus()))
                        .findFirst().orElse(null);
                if (Objects.nonNull(userChannelAccountDTO)
                        && Objects.nonNull(userChannelAccountDTO.getChannelUserIdentifyDTO())) {
                    ChannelUserIdentifyDTO channelUserIdentifyDTO = userChannelAccountDTO.getChannelUserIdentifyDTO();
                    return Pair.of(channelUserIdentifyDTO.getUnionId(), channelUserIdentifyDTO.getOpenid());
                }
            }
        }
        return null;
    }

    public UserCoreDTO queryUserCoreInfo(String uid) {
        UserCoreQueryRequest request = new UserCoreQueryRequest();
        request.setUid(uid);
        request.setNeedExtend(false);
        acquire("queryUserCoreInfo", USER_CORE_INFO_RATELIMITER, request, "调用UserCoreDependency.queryUserCoreInfo");

        HttpResult<UserCoreQueryResponse> result = userCoreBaseClient.queryUserCoreInfo(request);
        if (result.isSuccess() && Objects.nonNull(result.getData())
                && Objects.nonNull(result.getData().getUserCoreDTO())) {
            return result.getData().getUserCoreDTO();
        }
        return new UserCoreDTO();
    }

    public UserTutorRelationDTO queryUserTutorRelation(String uid) {
        TutorBaseRequest request = new TutorBaseRequest();
        request.setUid(uid);
        HttpResult<UserTutorRelationDTO> result = irisTutorRelationManageClient.queryUserTutorRelation(request);
        if (result.isSuccess() && Objects.nonNull(result.getData())) {
            return Optional.ofNullable(result.getData()).orElseGet(UserTutorRelationDTO::new);
        }
        return new UserTutorRelationDTO();
    }

    //查询用户成为见习会员时间
    public Long queryTraineeTime(String uid) {
        UserBaseRequest userBaseRequest = new UserBaseRequest();
        userBaseRequest.setUid(uid);
        TraineeTimeResponse response = HttpUtil.httpCall(userBaseRequest,
                irisUserActivityClient::queryTraineeTime, BizCommErrorCode.RPC_ERROR);
        log.info("查询用户成为见习会员时间：uid：{}，req：{}，res：{}", uid, JSON.toJSONString(userBaseRequest), JSON.toJSONString(response));
        return Optional.ofNullable(response).map(TraineeTimeResponse::getTimeStamp).orElse(null);
    }

    //查询用户等级、以及成为超级会员时间
    public UserLevelResponse queryUserLevel(String uid, Boolean isTimeStamp) {
        UserLevelRequest userLevelRequest = new UserLevelRequest();
        userLevelRequest.setUid(uid);
        if (Objects.nonNull(isTimeStamp)) {
            userLevelRequest.setIsTimeStamp(isTimeStamp);
        }
        HttpResult<UserLevelResponse> result = irisUserActivityClient
                .queryUserLevel(userLevelRequest);
        log.info("查询用户等级以及成为超级会员时间：uid：{}，req：{}，res：{}", uid, JSON.toJSONString(userLevelRequest), JSON.toJSONString(result));
        if (result.isSuccess() && Objects.nonNull(result.getData())) {
            return result.getData();
        }
        return null;
    }

    //查询用户是否是特邀会员、以及成为特邀的时间
    public SpecialInviteResponse querySpecialInvite(String uid, Boolean isTimeStamp) {
        SpecialInviteRequest specialInviteRequest = new SpecialInviteRequest();
        specialInviteRequest.setUid(uid);
        if (Objects.nonNull(isTimeStamp)) {
            specialInviteRequest.setIsTimeStamp(isTimeStamp);
        }
        HttpResult<SpecialInviteResponse> result = irisUserActivityClient
                .querySpecialInvite(specialInviteRequest);
        log.info("查询用户是否是特邀会员以及成为特邀的时间：uid：{}，req：{}，res：{}", uid, JSON.toJSONString(specialInviteRequest), JSON.toJSONString(result));
        if (result != null && result.isSuccess() && Objects.nonNull(result.getData())) {
            return result.getData();
        }

        log.error("查询用户是否是特邀会员以及成为特邀的时间失败：uid：{}, 返回：{}", uid, result);
        return null;
    }

    //查询用户上级uid，以及是否是虚拟上级
    public SupervisorRelationResponse queryUserSupervisor(String uid) {
        UserBaseRequest userBaseRequest = new UserBaseRequest();
        userBaseRequest.setUid(uid);
        HttpResult<SupervisorRelationResponse> result = null;
        try {
            result = irisUserActivityClient.queryUserSupervisor(userBaseRequest);
            log.info("查询用户上级uid以及是否是虚拟上级：uid：{}，req：{}，res：{}", uid, JSON.toJSONString(userBaseRequest), JSON.toJSONString(result));
            if (result.isSuccess() && Objects.nonNull(result.getData())) {
                return result.getData();
            }
        } catch (Exception e) {
            log.error("UserCoreDependency.queryUserSupervisor failRequest:{} result: {}",
                    JsonUtils.toJsonString(userBaseRequest), result, e);
            throw new TRetailBizException(e);
        }
        log.error("UserCoreDependency.queryUserSupervisor failRequest:{} result:{}",
                JsonUtils.toJsonString(userBaseRequest), result);
        throw new TRetailBizException(result.getCode(), result.getMsg());
    }

    public List<UserLevelCountResponse> countUserLevelByParentUid(UserLevelCountRequest request) {
        HttpResult<List<UserLevelCountResponse>> result = null;
        try {
            result = irisUserInfoClient.countUserLevelByParentUid(request);
            if (result.isSuccess() && Objects.nonNull(result.getData())) {
                return result.getData();
            }
        } catch (Exception e) {
            log.error("countUserLevelByParentUid error,request:{},response:{}", JSON.toJSONString(request),
                    JSON.toJSONString(result));
        }
        return Lists.newArrayList();

    }

    /**
     * 查询用户当前等级和升到当前等级的时间
     *
     * @param uid
     * @return
     */
    public MemberTimeResponse queryUserMemberTime(String uid, String levelId) {
        //设置泳道标，防止qa找不到泳道
        TsfTagUtils.setLaneId(TsfTagUtils.getGroupLaneId());

        UserLevelRequest req = new UserLevelRequest();
        req.setUid(uid);
        req.setLevelId(levelId);
        HttpResult<MemberTimeResponse> result = null;
        try {
            result = irisUserActivityClient.queryUserMemberTime(req);
            log.info("查询用户当前等级和升到当前等级的时间：uid：{}，req：{}，res：{}", uid, JSON.toJSONString(req), JSON.toJSONString(result));
            if (result == null) {
                log.error("UserCoreDependency.queryUserMemberTime return null request:{} result: {}",
                        JsonUtils.toJsonString(req), result);
                throw new TRetailBizException(result.getCode(), result.getMsg());
            }
            if (result.isSuccess() && Objects.nonNull(result.getData())) {
                return result.getData();
            }
        } catch (Exception e) {
            log.error("UserCoreDependency.queryUserMemberTime exception request:{} result: {}",
                    JsonUtils.toJsonString(req), result, e);
            throw new TRetailBizException(e);
        }
        log.error("UserCoreDependency.queryUserMemberTime exception request:{} result: {}",
                JsonUtils.toJsonString(req), result);
        throw new TRetailBizException(result.getCode(), result.getMsg());
    }

    /**
     * 批量查询用户信息
     *
     * @param request
     * @return
     */
    public List<UserWideDTO> batchQueryUserList(IrisUserWideListQueryRequest request) {
        log.info("调用UserDependency.batchQueryUserList，请求参数：{}", JSON.toJSONString(request));

        DependencyConfig.Config queryListConfig = dependencyConfig.getConfigs().get("queryList");
        Integer batchSize = Optional.ofNullable(queryListConfig).map(DependencyConfig.Config::getBatchSize).orElse(50);

        List<String> uidList = request.getUidList().stream()
                .distinct().collect(Collectors.toList());
        List<UserWideDTO> resList = Lists.newArrayListWithCapacity(uidList.size());
        List<List<String>> partition = Lists.partition(uidList, batchSize);
        if (request.getSaasId() == null) {
            request.setSaasId(saasId);
        }

        for (List<String> list : partition) {
            request.setUidList(list);
            resList.addAll(doBatchQueryUserList(request));
        }

        log.info("调用UserDependency.batchQueryUserList，请求参数：{}，请求结果：{}",
                JSON.toJSONString(request), JSON.toJSONString(resList));
        return resList;
    }

    private List<UserWideDTO> doBatchQueryUserList(IrisUserWideListQueryRequest request) {
        acquire("queryList", USER_WIDE_LIST_RATELIMITER, request, "调用UserDependency.doBatchQueryUserList");

        HttpResult<UserWideListResponse> result = null;
        try {
            result = userWideCoreClient.queryList(request);
        } catch (Exception e) {
            log.error("UserDependency.doBatchQueryUserList失败：", e);
        }

        UserWideListResponse response = HttpUtil.handleResult(result);
        if (response == null || CollectionUtil.isEmpty(response.getList())) {
            return Collections.emptyList();
        }

        List<UserWideDTO> list = response.getList();
        log.info("调用UserDependency.doBatchQueryUserInfo，请求参数：{}，请求结果：{}",
                JSON.toJSONString(request), JSON.toJSONString(list));
        return list;
    }

    /**
     * 获取用户快照数据
     *
     * @param request
     * @return
     */
    private IrisUserDTO getValidTimeInfo(IrisUserValidTimeInfoRequest request) {

        HttpResult<IrisUserDTO> result = null;
        try {
            log.info("UserCoreDependency.getValidTimeInfo 开始获取用户快照信息,request:{}", JSONObject.toJSONString(request));
            result = irisUserInfoClient.getValidTimeInfo(request);
            if (result == null) {
                log.error("UserCoreDependency.getValidTimeInfo return null request:{} result: {}",
                        JsonUtils.toJsonString(request), result);
                throw new TRetailBizException(result.getCode(), result.getMsg());
            }
            if (result.isSuccess() && Objects.nonNull(result.getData())) {
                return result.getData();
            }
        } catch (Exception e) {
            log.error("UserCoreDependency.getValidTimeInfo exception request:{} result: {}",
                    JsonUtils.toJsonString(request), result, e);
            throw new TRetailBizException(e);
        }
        log.error("UserCoreDependency.getValidTimeInfo exception request:{} result: {}",
                JsonUtils.toJsonString(request), result);
        throw new TRetailBizException(result.getCode(), result.getMsg());

    }

    /**
     * 根据unionId查询用户信息
     * @param unionId
     * @return
     */
    public UserUnionIdResponse getUserInfoByUnionId(String unionId) {
        UserUnionIdRequest request = new UserUnionIdRequest();
        request.setUnionId(unionId);
        request.setSaasId(saasId);
        request.setSource(IrisUserSourceFromEnum.QF_ACTIVITY.getCode());
        HttpResult<UserUnionIdResponse> result = userWideCoreClient.getUserInfoByUnionIdV2(request);
        log.info("根据unionId查询用户信息：unionId：{}，req：{}，res：{}", unionId, JSON.toJSONString(request), JSON.toJSONString(result));
        return HttpUtil.handleResult(result);
    }
}
